/*
 * File Name:               XRandom.cs
 *
 * Description:             伪随机方案
 * Author:                  lisiyu <576603306@qq.com>
 * Create Date:             2016/11/21
 */

using System;

/// <summary>
/// 设定一个种子 那么随机序列将会被固定 
/// </summary>
internal class XRandom
{
    private static UInt64 seed = 100;

    public static void setSeed(UInt64 nseed)
    {
        seed = (nseed ^ 0x5DEECE66DUL) & ((1UL << 48) - 1);

        Range(0, 10);
    }

    /// <summary>
    /// 仿照Unity的接口 
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static int Range(int min, int max)
    {
        return NextInt(max - min) + min;
    }

    /// <summary>
    /// 返回以center 为中心， radius 为半径范围内随机一个点
    /// </summary>
    /// <param name="center"></param>
    /// <param name="radius"></param>
    /// <returns></returns>
    public static XVector2 RangePointInCircle(XVector2 center,XNumber radius)
    {
        if (XIntMath.Approximately(radius, XNumber.zero))
            return center;
        var angle = Range(0, 360);
        var lenth = Range(0, radius);
        var endDir = XQuaternion.AngleAxis(angle, XVector3.up) * XVector3.forward;

        return center + endDir.xz * lenth;
    }


    /// <summary>
    /// 仿照Unity的接口
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static XNumber Range(XNumber min, XNumber max)
    {
        return (max - min) * NextInt(1001) / (XNumber)1000 + min;
    }

    /// <summary>
    /// 随机判定是否成功
    /// </summary>
    /// <param name="rate">0-100的值, 即成功几率的百分比</param>
    /// <returns></returns>
    public static bool Success(XNumber rate)
    {
        var range = Range(XNumber.zero, XNumber.hundred);
        if (range < rate)
            return true;
        return false;
    }

    //public static float Range(float min, float max)
    //{
    //    return (max - min) * NextInt(1001) / 1000f + min;
    //}

    private static int NextInt(int n)
    {
        if (n <= 0) throw new ArgumentException("min must be less than max");

        if ((n & -n) == n)  // i.e., n is a power of 2
            return (int)((n * (long)Next(31)) >> 31);

        long bits, val;
        do
        {
            bits = Next(31);
            val = bits % (UInt32)n;
        }
        while (bits - val + (n - 1) < 0);

        return (int)val;
    }

    private static UInt32 Next(int bits)
    {
        seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);

        return (UInt32)(seed >> (48 - bits));
    }
}